package guda.house.web.action.front.pay;

import com.alibaba.fastjson.JSONObject;
import guda.grape.autogen.common.page.BizResult;
import guda.grape.util.RequestUtil;
import guda.house.biz.WxPayOrderBiz;
import guda.house.biz.config.WeixinConfig;
import guda.house.biz.constants.CommonResultCode;
import guda.house.biz.form.front.BindSuiteForm;
import guda.house.biz.helper.alipay.AlipayHelper;
import guda.house.biz.helper.weixin.HttpsRequest;
import guda.house.biz.helper.weixin.WeixinUtil;
import guda.house.biz.helper.weixin.form.WeixinRequest;
import guda.house.biz.helper.weixin.form.WeixinResponse;
import guda.house.biz.util.StringUtil;
import guda.house.dal.dataobject.WxAccessDO;
import guda.house.dal.dataobject.WxPayOrderDO;
import guda.house.web.action.front.wx.WxIndexAction;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by well on 16/5/29.
 */
@Controller
@RequestMapping(value = "front")
public class Weixin {

    private Logger log = LoggerFactory.getLogger(Weixin.class);


    @Autowired
    private WxPayOrderBiz wxPayOrderBiz;


    private static final String RETURN_URL = "/front/wx/payback/weixinBack.htm";
    private static final String WEIXIN_PAY_GATE = "https://api.mch.weixin.qq.com/pay/unifiedorder";



    @RequestMapping(value = "pay/weixin.htm", method = RequestMethod.GET)
    public String index(HttpServletRequest request, ModelMap modelMap) {
        long suiteId = RequestUtil.getLong(request, "suiteId");

        if(suiteId ==0){
            return "redirect:/front/error.htm?code=" + CommonResultCode.PARAM_MISS;
        }
        BizResult bizResult = wxPayOrderBiz.prepareForPay(suiteId);
        if(!bizResult.success){
            return "redirect:/front/error.htm?code=" + bizResult.code;
        }
        modelMap.putAll(bizResult.data);
        WxPayOrderDO wxPayOrderDO = (WxPayOrderDO)bizResult.data.get("wxPayOrderDO");
        WxAccessDO wxAccessById = (WxAccessDO)bizResult.data.get("wxAccessById");
        String suiteName = (String)bizResult.data.get("suiteName");
        String redirectURI = WxIndexAction.getFullContextPath(request);
        try {
            String notifyUrl = redirectURI + RETURN_URL;


            WeixinRequest weixinRequest = new WeixinRequest();
            String orderNo = RandomNoHelper.next(wxPayOrderDO.getOrderNo());
            weixinRequest.setAppid(WeixinConfig.appId);
            weixinRequest.setMch_id(WeixinConfig.mhc_id);
            weixinRequest.setNonce_str(orderNo);
            weixinRequest.setBody(StringUtil.cut(suiteName, 25));
            weixinRequest.setOut_trade_no(orderNo);
            weixinRequest.setTotal_fee(String.valueOf(wxPayOrderDO.getPayTotal()));
            weixinRequest.setSpbill_create_ip(request.getRemoteAddr());
            weixinRequest.setNotify_url(notifyUrl);
            weixinRequest.setProduct_id(String.valueOf(wxPayOrderDO.getOrderId()));
            weixinRequest.setTrade_type("JSAPI");
            weixinRequest.setOpenid(wxAccessById.getOpenid());
            Map<String, String> stringStringMap = weixinRequest.toParamMap();
            String queryString = AlipayHelper.createQueryString(stringStringMap);
            queryString = queryString + "&key=" + WeixinConfig.appSecret;
            log.info("weixin pay:" + queryString);
            String sign = DigestUtils.md5Hex(queryString).toUpperCase();
            weixinRequest.setSign(sign);
            HttpsRequest httpsRequest = new HttpsRequest();
            String xml = httpsRequest.sendPost(WEIXIN_PAY_GATE, weixinRequest.toXML());
            WeixinResponse weixinReponse = WeixinUtil.parse(xml, WeixinResponse.class);
            log.info("weixin pay response:" + JSONObject.toJSONString(weixinReponse));
            Map<String, String> map = sign(weixinReponse);
            modelMap.putAll(map);
        } catch (Exception e) {
            log.error("", e);
        }

        return "front/pay/weixin.vm";
    }

    private Map<String, String> sign(WeixinResponse weixinResponse) {
        try {
            Map<String, String> param = new HashMap<String, String>();
            param.put("appId", weixinResponse.getAppid());
            param.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
            param.put("nonceStr", RandomNoHelper.next(weixinResponse.getNonce_str()));
            param.put("package", ("prepay_id=" + weixinResponse.getPrepay_id()));
            param.put("signType", "MD5");
            //param.put("paySign",weixinResponse.getAppid());
            String queryString = AlipayHelper.createQueryString(param) + "&key=" + WeixinConfig.appSecret;

            param.put("paySign", DigestUtils.md5Hex(queryString).toUpperCase());
            param.put("prepay_id", weixinResponse.getPrepay_id());
            return param;
        } catch (Exception e) {
            log.error("", e);
        }
        return null;
    }

    static class RandomNoHelper {
        static AtomicInteger atomicInteger = new AtomicInteger(0);

        private static String random() {
            int i = atomicInteger.addAndGet(1);
            if (i > 100) {
                atomicInteger.set(0);
            }
            return appendZero(String.valueOf(i), 3);
        }

        private static String next(String orderNo) {
            return orderNo + random();
        }

        private static String appendZero(String str, int strLength) {
            int strLen = str.length();
            StringBuilder buf = new StringBuilder();
            if (strLen < strLength) {
                for (int i = 0, len = strLength - strLen; i < len; ++i) {
                    buf.append("0");
                }
            }
            buf.append(str);
            return buf.toString();
        }

    }
}
